package com.walala.dispatcher.service;

import java.lang.annotation.Annotation;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.walala.dispatcher.annotion.ExecutorHandler;
import com.walala.dispatcher.executor.DispatcherExecutor;
import com.walala.dispatcher.global.Constant;
import com.walala.dispatcher.pojo.RequestMsg;
import com.walala.dispatcher.pojo.ServerInfo;
import com.walala.dispatcher.redis.RedisClient;
import com.walala.dispatcher.utils.LoadClassUtil;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.socket.DatagramPacket;
import redis.clients.jedis.Jedis;

public class DispatcherService {
	
	private static Logger logger = LoggerFactory.getLogger(DispatcherService.class);
	
	//handler执行类缓存
	private static ConcurrentMap<Integer, DispatcherExecutor> EXECUTOR_MAP = new ConcurrentHashMap<Integer, DispatcherExecutor>();
	public static ConcurrentHashMap<String,ServerInfo> CONNECTOR_DOWN_MAP = new ConcurrentHashMap<String,ServerInfo>();
	
	
	//初始化逻辑处理类
    static {
        try {
            Package pack = DispatcherExecutor.class.getPackage();
            Set<Class<?>> clazzSet = LoadClassUtil.getClasses(pack.getName());
            for (Class clz : clazzSet) {
                try {
            		DispatcherExecutor executor = (DispatcherExecutor) clz.newInstance();
            		if(executor.type != 0){
            			EXECUTOR_MAP.put(executor.type,executor);
            		}
                } catch (Exception e) {
                		logger.error("error:{}", e);
                    e.printStackTrace();
                } 
            }
        } catch (Exception e) {
        	logger.error("error:{}", e);
            e.printStackTrace();
        }
    }

	public static void process(ChannelHandlerContext ctx, DatagramPacket packet, String msg) {
		
		RequestMsg requestMsg = JSON.parseObject(msg,RequestMsg.class);
		DispatcherExecutor dispatcherProcess = EXECUTOR_MAP.get(requestMsg.getRequestType());
		dispatcherProcess.dispatcher(ctx,packet,requestMsg);
		
	}
	
	/**
	 * 定时检查服务状态
	 */
	public static void init(){
		
		Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(new Runnable() {
			
			@Override
			public void run() {
				checkGetwayServer();
			}
		}, 6 * 60 * 1000, 60 * 1000, TimeUnit.MILLISECONDS);
		
	}

	protected static void checkGetwayServer() {
		
		Jedis cluster = RedisClient.intance.getCluster();
		Map<String, String> map = cluster.hgetAll(Constant.CONNECTOR_SERVER_INFO);
        long nowTime = System.currentTimeMillis();
        if (map != null) {
            Set<Map.Entry<String, String>> set = map.entrySet();
            for (Map.Entry<String, String> entry : set) {
            	ServerInfo server = JSON.parseObject(entry.getValue(), ServerInfo.class);
                long lastUpdateTime = server.getUpdateTime();
                String ipPort = entry.getKey();
                if (DispatcherService.CONNECTOR_DOWN_MAP.containsKey(ipPort)) {
                    DispatcherService.CONNECTOR_DOWN_MAP.remove(ipPort);
                }
                //客户端每3分钟一定会汇报一次服务
                if (nowTime - lastUpdateTime > 5 * 60 * 1000) {
                    //redis del
                    cluster.hdel(Constant.CONNECTOR_SERVER_INFO, ipPort);
                    //记录坏掉的服务
                    CONNECTOR_DOWN_MAP.put(ipPort,server);

                    logger.error("connector检测 --> 1. 存在服务没有汇报状态,请检查服务状态,服务地址:{},服务类型:{}", ipPort, server.getType());
                }
            }
            if (set.isEmpty()) {
            	logger.error("connector检测 --> 2. 服务资源为空,客户端用户没有汇报状态到调度服务,请检查各服务,定时及时汇报状态!");
            }
            logger.info("connector检测 --> 3. 当前调度服务所有服务资源内容:{}", JSON.toJSONString(map));
        } else {
        	logger.error("connector检测 --> 4. 服务资源为空,客户端用户没有汇报状态到调度服务,请检查......");
        }
		
		
	}
	
}
